#ifndef TCP_SERVER_SOCKETUTILS_H
#define TCP_SERVER_SOCKETUTILS_H

#include <arpa/inet.h>

namespace sockets {
    /**
     * 创建非阻塞文件描述符, 创建失败就终止程序
     */
    int createNonblockingOrDie(sa_family_t family);

    int connect(int sockfd, const struct sockaddr *addr);

    void bindOrDie(int sockfd, const struct sockaddr *addr);

    void listenOrDie(int sockfd);

    int accept(int sockfd, struct sockaddr_in6 *addr);

    ssize_t read(int sockfd, void *buf, size_t count);

    ssize_t readv(int sockfd, const struct iovec *iov, int iovcnt);

    ssize_t write(int sockfd, const void *buf, size_t count);

    void close(int sockfd);

    void shutdownWrite(int sockfd);

    void toIpPort(char *buf, size_t size,
                  const struct sockaddr *addr);

    void toIp(char *buf, size_t size,
              const struct sockaddr *addr);

    void fromIpPort(const char *ip, uint16_t port,
                    struct sockaddr_in *addr);

    void fromIpPort(const char *ip, uint16_t port,
                    struct sockaddr_in6 *addr);

    int getSocketError(int sockfd);

    /* 下面是类型转化的封装函数 */
    const struct sockaddr *sockaddr_cast(const struct sockaddr_in *addr);

    const struct sockaddr *sockaddr_cast(const struct sockaddr_in6 *addr);

    struct sockaddr *sockaddr_cast(struct sockaddr_in6 *addr);

    struct sockaddr *sockaddr_cast(struct sockaddr_in *addr);

    const struct sockaddr_in *sockaddr_in_cast(const struct sockaddr *addr);

    const struct sockaddr_in6 *sockaddr_in6_cast(const struct sockaddr *addr);

    /**
     * 用于获取socket文件描述符在本地保存的地址信息
     * @param sockfd 要获取的文件描述符的地址信息
     * @return
     */
    //  struct sockaddr_in getLocalAddr(int sockfd);

    /**
     * 将连接到socket的对等方的地址信息存放起来
     * @param sockfd
     * @return
     */
    //  struct sockaddr_in getPeerAddr(int sockfd);

    bool isSelfConnect(int sockfd);
}


#endif //TCP_SERVER_SOCKETUTILS_H
